﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.Security;
using System.Security.Permissions;
using Microsoft.VisualStudio.Tools.Office.Runtime.Security;
using System.Diagnostics;
using System.IO;

namespace Movistar.SMS.Setup.InclusionListCustomAction
{
    [RunInstaller(true)]
    public class TrustInstaller : Installer
    {
        const string RSA_PublicKey = "<RSAKeyValue><Modulus>xWAwQVCmEPvpVglMxoyA5M7BWRV8d0GsADwOwkQthTRwzSLeVktU7l68/uVT6MgrtbiwtINBhkrcFMnVmv7R1CoWZ/LpTSc6jN5LxLjBcGu7p0f4NdDffaBxvRNeODXMCVg4s77ZnYSTR7jQEPhBocEcyIRXdhOGbVc40CBAF9c=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

        public override void Install(IDictionary stateSaver)
        {
            try
            {
                SecurityPermission permission = new SecurityPermission(PermissionState.Unrestricted);
                permission.Demand();

                string deploymentLocation = Context.Parameters["deploymentLocation"];

                if (String.IsNullOrEmpty(deploymentLocation))
                    throw new InstallException("Localización de descarga de ClickOnce no configurada. La instalación no puede continuar.");

                Uri deploymentManifestLocation = null;

                if (Uri.TryCreate(deploymentLocation, UriKind.RelativeOrAbsolute, out deploymentManifestLocation) == false)
                {
                    throw new InstallException("La localización de descarga de ClickOnce es inválida.");
                }

                AddInSecurityEntry entry = new AddInSecurityEntry(deploymentManifestLocation, RSA_PublicKey);

                UserInclusionList.Add(entry);

                stateSaver.Add("entryKey", deploymentManifestLocation);

                string arguments = String.Format("/I \"{0}\"", deploymentLocation);

                int exitCode = ExecuteVSTOInstaller(arguments);

                stateSaver.Add("deploymentLocation", deploymentLocation);
            }
            catch (SecurityException)
            {
                throw new InstallException("10 - No tiene suficientes permisos para instalar esta aplicación.");
            }
            catch (Exception ex)
            {
                throw new InstallException("11 - " + ex.Message);
            }

            base.Install(stateSaver);
        }

        public override void Uninstall(IDictionary savedState)
        {
            try
            {
                Uri deploymentManifestLocation = (Uri)savedState["entryKey"];

                if (deploymentManifestLocation != null)
                {
                    UserInclusionList.Remove(deploymentManifestLocation);
                }

                string deploymentLocation = (string)savedState["deploymentLocation"];

                if (deploymentLocation != null)
                {
                    string arguments = String.Format("/U \"{0}\"", deploymentLocation);

                    ExecuteVSTOInstaller(arguments);
                }
            }
            catch (Exception ex)
            {
                throw new InstallException("12 - " + ex.Message);
            }

            base.Uninstall(savedState);
        }

        public override void Commit(IDictionary savedState)
        {
            base.Commit(savedState);
        }

        public override void Rollback(IDictionary savedState)
        {
            base.Rollback(savedState);
        }

        int ExecuteVSTOInstaller(string arguments)
        {
            string basePath = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles);

            string subPath = @"Microsoft Shared\VSTO\9.0\VSTOInstaller.exe";

            string vstoInstallerPath = Path.Combine(basePath, subPath);

            if (File.Exists(vstoInstallerPath) == false)
            {
                throw new InstallException("El instalador de Visual Studio Tools for Office no se ha encontrado.");
            }

            ProcessStartInfo startInfo = new ProcessStartInfo(vstoInstallerPath);

            startInfo.Arguments = arguments;
            startInfo.WorkingDirectory = basePath;
            Process process = Process.Start(startInfo);

            process.WaitForExit();

            return process.ExitCode;
        }
    }
}
